/**
 * File: ArcMapper.java
 * Created by: mhaimel
 * Created on: Mar 8, 2010
 * CVS:  $Id: ArcMapper.java 1.0 Mar 8, 2010 4:41:28 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.model.graph.io;

import uk.ac.ebi.curtain.model.graph.Arc;
import uk.ac.ebi.curtain.model.graph.Graph;
import uk.ac.ebi.curtain.model.graph.Node;
import uk.ac.ebi.curtain.model.graph.NodeEdge;

/**
 * @author mhaimel
 *
 */
public class ArcMapper<N,A> implements WriteMapper<Arc<N,A>>, ReadMapper<Arc<N,A>> {

	private static final char RIGHT_CHAR = 'R';
	private static final String RIGHT = ""+RIGHT_CHAR;
	private static final char LEFT_CHAR = 'L';
	private static final String LEFT = ""+LEFT_CHAR;
	private static final String[] header = new String[]{"ArcId","left_node_Id","right_node_Id", "left_node_pos","right_node_pos"};

	@Override
	public String[] getHeader() {
		return header;
	}

	@Override
	public Object[] toArray(Arc<N, A> value) {
		return new Object[]{
				value.getId(),
				value.getLeft().getId(),
				value.getRight().getId(),
				toString(value.onLeftNode().asBoolean()),
				toString(value.onRightNode().asBoolean())
		};
	}

	@Override
	public int getFieldCount() {
		return header.length;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Arc<N, A> loadValue(String[] array, int i, Graph graph) {
		Long aId = Long.valueOf(array[i++]);
		Long lId = Long.valueOf(array[i++]);
		Long rId = Long.valueOf(array[i++]);
		NodeEdge lPos = posFromString(array[i++]);
		NodeEdge rPos = posFromString(array[i++]);
		Node left = graph.getNode(lId);
		Node right = graph.getNode(rId);
		Arc arc = graph.forceCreateArc(aId, left, right, lPos,rPos);
		return arc;
	}
	
	private NodeEdge posFromString(String s){
		if(s.length() != 1){
			throw new IllegalArgumentException("For position (left/right) one character expected: " + s);			
		}
		switch (s.charAt(0)) {
		case LEFT_CHAR:
			return NodeEdge.Start;
		case RIGHT_CHAR:
			return NodeEdge.End;
		default:
			throw new IllegalArgumentException("Position (left/right) expected instead of " + s);
		}
	}
	
	private String toString(boolean bool){
		if(bool == NodeEdge.Start.asBoolean()){
			return LEFT;
		} else if(bool == NodeEdge.End.asBoolean()){
			return RIGHT;
		} else {
			throw new IllegalArgumentException("Only two states possible - arguement not allowed: " + bool);
		}
	}
	
}
